package com.roamer.audition.web.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.*;
import org.springframework.http.converter.cbor.MappingJackson2CborHttpMessageConverter;
import org.springframework.http.converter.feed.AtomFeedHttpMessageConverter;
import org.springframework.http.converter.feed.RssChannelHttpMessageConverter;
import org.springframework.http.converter.json.GsonHttpMessageConverter;
import org.springframework.http.converter.json.JsonbHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.smile.MappingJackson2SmileHttpMessageConverter;
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
import org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter;
import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter;
import org.springframework.http.converter.xml.SourceHttpMessageConverter;
import org.springframework.util.ClassUtils;
import org.springframework.web.client.RestTemplate;

import java.util.Arrays;
import java.util.List;

/**
 * RestTemplate 配置
 *
 * @author roamer
 * @version V1.0
 * @date 2019-09-05 15:17
 */
@Configuration
public class RestTemplateConfig {

    private static final boolean ROME_PRESENT = ClassUtils.isPresent("com.rometools.rome.feed.WireFeed",
                                                                     RestTemplate.class.getClassLoader());
    private static final boolean JAXB_2_PRESENT = ClassUtils.isPresent("javax.xml.bind.Binder",
                                                                       RestTemplate.class.getClassLoader());
    private static final boolean JACKSON_2_PRESENT = ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper",
                                                                          RestTemplate.class.getClassLoader()) && ClassUtils
            .isPresent("com.fasterxml.jackson.core.JsonGenerator", RestTemplate.class.getClassLoader());
    private static final boolean JACKSON_2_XML_PRESENT = ClassUtils.isPresent(
            "com.fasterxml.jackson.dataformat.xml.XmlMapper", RestTemplate.class.getClassLoader());
    private static final boolean JACKSON_2_SMILE_PRESENT = ClassUtils.isPresent(
            "com.fasterxml.jackson.dataformat.smile.SmileFactory", RestTemplate.class.getClassLoader());
    private static final boolean JACKSON_2_CBOR_PRESENT = ClassUtils.isPresent(
            "com.fasterxml.jackson.dataformat.cbor.CBORFactory", RestTemplate.class.getClassLoader());
    private static final boolean GSON_PRESENT = ClassUtils.isPresent("com.google.gson.Gson",
                                                                     RestTemplate.class.getClassLoader());
    private static final boolean JSONB_PRESENT = ClassUtils.isPresent("javax.json.bind.Jsonb",
                                                                      RestTemplate.class.getClassLoader());

    private final ObjectMapper objectMapper;

    private final RestTemplateBuilder builder;

    public RestTemplateConfig(ObjectMapper objectMapper, RestTemplateBuilder builder) {
        this.objectMapper = objectMapper;
        this.builder = builder;
    }

    /**
     * 使用RestTemplateBuilder来实例化RestTemplate对象
     *
     * @return {@code RestTemplate}
     */
    @Bean
    public RestTemplate restTemplate() {
        RestTemplate restTemplate = builder.build();
        List<HttpMessageConverter<?>> messageConverters = Lists.newArrayList();
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setObjectMapper(objectMapper);
        //不加会出现异常
        MediaType[] mediaTypes = new MediaType[]{MediaType.APPLICATION_JSON,
                MediaType.APPLICATION_OCTET_STREAM,
                MediaType.APPLICATION_JSON_UTF8,
                MediaType.TEXT_HTML,
                MediaType.TEXT_PLAIN,
                MediaType.TEXT_XML,
                MediaType.APPLICATION_STREAM_JSON,
                MediaType.APPLICATION_ATOM_XML,
                MediaType.APPLICATION_FORM_URLENCODED,
                MediaType.APPLICATION_PDF,};
        converter.setSupportedMediaTypes(Arrays.asList(mediaTypes));
        if (JACKSON_2_PRESENT) {
            messageConverters.add(converter);
        } else if (GSON_PRESENT) {
            messageConverters.add(new GsonHttpMessageConverter());
        } else if (JSONB_PRESENT) {
            messageConverters.add(new JsonbHttpMessageConverter());
        }
        messageConverters.add(new FormHttpMessageConverter());
        messageConverters.add(new ByteArrayHttpMessageConverter());
        messageConverters.add(new StringHttpMessageConverter());
        messageConverters.add(new ResourceHttpMessageConverter(false));
        messageConverters.add(new SourceHttpMessageConverter());
        messageConverters.add(new AllEncompassingFormHttpMessageConverter());
        if (ROME_PRESENT) {
            messageConverters.add(new AtomFeedHttpMessageConverter());
            messageConverters.add(new RssChannelHttpMessageConverter());
        }
        if (JACKSON_2_XML_PRESENT) {
            messageConverters.add(new MappingJackson2XmlHttpMessageConverter());
        } else if (JAXB_2_PRESENT) {
            messageConverters.add(new Jaxb2RootElementHttpMessageConverter());
        }
        if (JACKSON_2_SMILE_PRESENT) {
            messageConverters.add(new MappingJackson2SmileHttpMessageConverter());
        }
        if (JACKSON_2_CBOR_PRESENT) {
            messageConverters.add(new MappingJackson2CborHttpMessageConverter());
        }
        restTemplate.setMessageConverters(messageConverters);
        return restTemplate;
    }


}
